﻿using System.Xml;
using Windows.Foundation;

namespace LinkPad.Shapes
{
    public abstract class ManagedShape : IManagedShape
    {
        #region Constructors

        protected ManagedShape(ShapeManager shapeManager)
        {
            ShapeManager = shapeManager;
        }

        #endregion

        #region Properties

        /// <summary>
        ///  returns the bounding box of the shape
        /// </summary>
        public abstract Rect BoundingBox { get; }

        /// <summary>
        ///  returns the absolute bounding box of the shape in the real world
        /// </summary>
        public abstract Rect RealBoundingBox { get; }

        /// <summary>
        ///  returns true if the real bounding box is ready
        /// </summary>
        public virtual bool RealBoundingBoxReady
        {
            get
            {
                return true;
            }
        }

        public ShapeManager ShapeManager { get; protected set; }

        #endregion

        #region Methods

        /// <summary>
        ///  Adds all shapes contained by this managed shape to the end of the shape list of the canvas so after that it shows at the top
        /// </summary>
        public abstract void AddToCanvas();

        /// <summary>
        ///  Removes all shapes contained by this managed shape from the canvas
        /// </summary>
        public abstract void RemoveFromCanvas();

        /// <summary>
        ///  Returns all indices to the shapes contained by the managed shape added to the shape list of the canvas
        /// </summary>
        /// <returns>All indices sorted ascendingly</returns>
        public abstract int[] IndicesInCanvas();

        /// <summary>
        ///  Inserts the shapes contained by the managed shape to the specified location in the shape list of the canvas
        /// </summary>
        /// <param name="index">The specified location (which should be the lowest of all items if multiple</param>
        public abstract void InsertToCanvas(int index);

        /// <summary>
        ///  returns the distance between the shape and the specified point
        /// </summary>
        /// <param name="point">The point between which and the shape the distance is to be calculated</param>
        /// <returns>The distance or 0 or any negative value if the point is on the boundaries of or inside the shape</returns>
        public abstract double DistanceToPoint(Point point);

        /// <summary>
        ///  Changes the shape location and size as the view has zoomed to the specified rectangle 
        /// </summary>
        public abstract void Transform();

        /// <summary>
        ///  Saves the shape to the specified XML writer
        /// </summary>
        /// <param name="xmlWriter">XML writer to write the stream to</param>
        public abstract void WriteToXml(XmlWriter xmlWriter);

        /// <summary>
        ///  Loads the shape from the specified XML reader
        /// </summary>
        /// <param name="xmlReader">XML reader to read the stream from</param>
        /// <returns>true if reading is successful</returns>
        public abstract bool ReadFromXml(XmlReader xmlReader);

        /// <summary>
        ///  Notifies the shape manager of the change of the shape so it can for instance update its boundary dimension
        /// </summary>
        protected virtual void ShapeChanged()
        {
            ShapeManager.ShapeChanged(this);
        }

        #endregion
    }
}
